﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Drawing;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace ImplementationJeu
{
    [Serializable] public class SerializationXML
    {
        //Chemin fichier
        public string cheminIO { get; set; }

        //Jeu
        public int sonTour { get; set; }

        //Joueur
        public List<string> nomDesJoueurs { get; set; }
        public List<string> couleurDesJoueurs { get; set; }
        public List<string> civilDesJoueurs { get; set; }

        //Civilisation
        //Unité : type , x , y , mouv , att , def , aeteutil , vie , viemax
        public List<List<List<string>>> civilUnite { get; set; }
        //Ville :  x , y , nourriture , minerai , pop , nourHab , dureeProd , enCmde, x,y... des cases occupees
        public List<List<List<string>>> civilVille { get; set; }

        //Carte
        public int tailleCarte { get; set; }
        public List<List<int>> caseMapKeys { get; set; }
        //Case :  type(decoco ou normal), si decoco alors typecasesous sinon "empty"
        public List<List<string>> caseMapValues { get; set; }

        public SerializationXML() { }

        public SerializationXML(InterfaceJeu.Jeu jeu, string chemin)
        {
            //Initialisations
            cheminIO = chemin;

            /* Jeu */
            sonTour = jeu.sonTour;

            //Joueurs
            nomDesJoueurs = new List<string>();
            couleurDesJoueurs = new List<string>();
            civilDesJoueurs = new List<string>();

            //Civilisation
            civilUnite = new List<List<List<string>>>();
            civilVille = new List<List<List<string>>>();

            /* Joueurs */
            for (int id = 0; id < jeu.Joueurs.Count; id++)
            {
                InterfaceJeu.Joueur jj = jeu.Joueurs[id];

                nomDesJoueurs.Add(jj.nom);
                couleurDesJoueurs.Add(jj.couleur.Name);
                civilDesJoueurs.Add(jj.civilisation.GetType().ToString().Substring(30));

                List<List<string>> lesUnites = new List<List<string>>();
                List<List<string>> lesVilles = new List<List<string>>();

                /*Civilisations*/
                /*Unité*/
                foreach (InterfaceJeu.Unite unit in jj.civilisation.unites)
                {
                    lesUnites.Add(unit.getSerialInfo());
                }

                /*Villes*/
                foreach (InterfaceJeu.Ville vill in jj.civilisation.villes)
                {
                    lesVilles.Add(vill.getSerialInfo());
                }

                civilUnite.Add(lesUnites);
                civilVille.Add(lesVilles);
            }

            //Carte
            tailleCarte = jeu.Carte.TailleCote;
            caseMapKeys = new List<List<int>>();
            caseMapValues = new List<List<string>>();
            foreach (Coordonnees cc in jeu.Carte.fabriqueCase.caseMap.Keys)
            {
                caseMapKeys.Add(cc.getCoordSerial());
                caseMapValues.Add(jeu.Carte.fabriqueCase.caseMap[cc].getSerialInfo());
            }
        }

        //Serialization
        public void sauvegarderPartie()
        {
            FileStream file = File.Open(cheminIO, FileMode.Create);
            XmlSerializer serializer = new XmlSerializer(typeof(Serialization));
            serializer.Serialize(file, this);
            file.Close();
        }

        //Deserialization
        public static void chargerPartie(string filename)
        {
            FileStream file = File.Open(filename, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(Serialization));
            SerializationXML partieSauvegardee = (SerializationXML)serializer.Deserialize(file);
            file.Close();

            Jeu partieReprise = ImplementationJeu.Jeu.Instance;
            //Jeu
            partieReprise.sonTour = partieSauvegardee.sonTour;

            //Carte
            partieReprise.Carte = new Carte();
            partieReprise.Carte.fabriqueCase = new FabriqueCase();
            partieReprise.Carte.fabriqueCase.caseMap = new Dictionary<InterfaceJeu.Coordonnees, InterfaceJeu.Case>();
            partieReprise.Carte.TailleCote = partieSauvegardee.tailleCarte;

            for (int indparcour = 0; indparcour < partieSauvegardee.caseMapKeys.Count; indparcour++)
            {
                List<int> coordonnee = partieSauvegardee.caseMapKeys[indparcour];
                Coordonnees coco = new Coordonnees(Convert.ToInt32(coordonnee[0]), Convert.ToInt32(coordonnee[1]));
                
                List<string> lacase = partieSauvegardee.caseMapValues[indparcour];
                //Case :  type(decoco ou normal), si decoco alors typecasesous sinon "empty"
                InterfaceJeu.Case casevraie = null;
                InterfaceJeu.Case caseDecoSiBesoin = null;

                if (lacase[1] == "empty")
                {
                    if (lacase[0] == "CasePlaine")
                        casevraie = new CasePlaine(coco);
                    if (lacase[0] == "CaseMontagne")
                        casevraie = new CaseMontagne(coco);
                    if (lacase[0] == "CaseDesert")
                        casevraie = new CaseDesert(coco);
                }
                else
                {
                    if (lacase[1] == "CasePlaine")
                        caseDecoSiBesoin = new CasePlaine(coco);
                    if (lacase[1] == "CaseMontagne")
                        caseDecoSiBesoin = new CaseMontagne(coco);
                    if (lacase[1] == "CaseDesert")
                        caseDecoSiBesoin = new CaseDesert(coco);
                    if (lacase[0] == "Fer")
                        casevraie = new Fer(caseDecoSiBesoin);
                    if (lacase[0] == "Fruit")
                        casevraie = new Fruit(caseDecoSiBesoin);
                }

                partieReprise.Carte.fabriqueCase.caseMap.Add(coco, casevraie);
            }

            //Joueurs
            partieReprise.Joueurs = new List<InterfaceJeu.Joueur>(partieSauvegardee.nomDesJoueurs.Count);
            for (int i = 0; i < partieSauvegardee.nomDesJoueurs.Count; i++)
            {
                Joueur j = new Joueur();
                j.caseVisible = new List<InterfaceJeu.Coordonnees>();

                //L'indice permet d'obtenir les infos du joueur
                j.nom = partieSauvegardee.nomDesJoueurs[i];
                j.couleur = Color.FromName(partieSauvegardee.couleurDesJoueurs[i]);
                InterfaceJeu.Civilisation civilResult = null;
                if (partieSauvegardee.civilDesJoueurs[i] == "EII")
                    civilResult = new CivilisationEII();
                if (partieSauvegardee.civilDesJoueurs[i] == "INFO")
                    civilResult = new CivilisationINFO();
                if (partieSauvegardee.civilDesJoueurs[i] == "STPI")
                    civilResult = new CivilisationSTPI();
                if (partieSauvegardee.civilDesJoueurs[i] == "SRC")
                    civilResult = new CivilisationSRC();
                if (partieSauvegardee.civilDesJoueurs[i] == "GMA")
                    civilResult = new CivilisationGMA();
                if (partieSauvegardee.civilDesJoueurs[i] == "SGM")
                    civilResult = new CivilisationSGM();
                if (partieSauvegardee.civilDesJoueurs[i] == "GCU")
                    civilResult = new CivilisationGCU();
                j.civilisation = civilResult;

                //Lecture des unités de la civilisation
                //Unité : type , x , y , mouv , aeteutil , vie
                //public List<List<List<string>>> civilUnite { get; set; }
                List<List<string>> lesUnitesDeLaCivilDeCeJoueur = partieSauvegardee.civilUnite[i];

                foreach (List<string> unites in lesUnitesDeLaCivilDeCeJoueur)
                {
                    InterfaceJeu.Unite uniteToAdd = null;
                    string typeUnite = unites[0];
                    string xPosit = unites[1];
                    string yPosit = unites[2];

                    if (typeUnite == "EnseignantINFO")
                        uniteToAdd = new EnseignantINFO(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit),Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantINFO")
                        uniteToAdd = new EtudiantINFO(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurLEPLUMEY")
                        uniteToAdd = new DirecteurLEPLUMEY(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantSRC")
                        uniteToAdd = new EnseignantSRC(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantSRC")
                        uniteToAdd = new EtudiantSRC(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurLOISON")
                        uniteToAdd = new DirecteurLOISON(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantEII")
                        uniteToAdd = new EnseignantEII(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantEII")
                        uniteToAdd = new EtudiantEII(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurBEDAT")
                        uniteToAdd = new DirecteurBEDAT(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantGMA")
                        uniteToAdd = new EnseignantGMA(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantGMA")
                        uniteToAdd = new EtudiantGMA(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurSOHIER")
                        uniteToAdd = new DirecteurSOHIER(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantSTPI")
                        uniteToAdd = new EnseignantSTPI(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantSTPI")
                        uniteToAdd = new EtudiantSTPI(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurBENHLAL")
                        uniteToAdd = new DirecteurBENHLAL(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantGCU")
                        uniteToAdd = new EnseignantGCU(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantGCU")
                        uniteToAdd = new EtudiantGCU(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurPRINCEAGBODJAN")
                        uniteToAdd = new DirecteurAGBODJAN(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EnseignantSGM")
                        uniteToAdd = new EnseignantSGM(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "EtudiantSGM")
                        uniteToAdd = new EtudiantSGM(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));
                    if (typeUnite == "DirecteurDURAND")
                        uniteToAdd = new DirecteurDURAND(j.civilisation, new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit)));

                    string mouv = unites[3];
                    string aeteutil = unites[4];
                    string vie = unites[5];
                    uniteToAdd.nbMouvement = Convert.ToInt32(mouv);
                    uniteToAdd.aEteUtilise = (aeteutil == "0");
                    uniteToAdd.pointDeVie = Convert.ToInt32(vie);

                    j.civilisation.unites.Add(uniteToAdd);
                    if (uniteToAdd is InterfaceJeu.Directeur)
                        j.civilisation.chef =(InterfaceJeu.Directeur) uniteToAdd;



                }

                //Ville :  x , y , nourriture , minerai , pop , nourHab , dureeProd , enCmde, x,y... des cases occupees
                //public List<List<List<string>>> civilVille { get; set; }
                List<List<string>> lesVillesDeLaCivilDeCeJoueur = partieSauvegardee.civilVille[i];

                foreach (List<string> ville in lesVillesDeLaCivilDeCeJoueur)
                {
                    InterfaceJeu.Ville villeToAdd = null;
                    string xPosit = ville[0];
                    string yPosit = ville[1];

                    Coordonnees cc = new Coordonnees(Convert.ToInt32(xPosit), Convert.ToInt32(yPosit));
                    villeToAdd = new Ville(ImplementationJeu.Jeu.Instance.Carte.obtenirCase(cc),j.civilisation);
                    
                    string nour = ville[2];
                    string miner = ville[3];
                    string popu = ville[4];
                    string seuilNourHab = ville[5];
                    string dureeProd = ville[6];
                    string enComm = ville[7];
                    villeToAdd.ressources["nourriture"] = Convert.ToInt32(nour);
                    villeToAdd.ressources["minerai"] = Convert.ToInt32(miner);
                    villeToAdd.population = Convert.ToInt32(popu);
                    villeToAdd.nourritureHab = Convert.ToInt32(seuilNourHab);
                    villeToAdd.dureeAttenteProduction = Convert.ToInt32(dureeProd);
                    villeToAdd.uniteEnCommande = Convert.ToInt32(enComm);

                    //cases occupees
                    for (int index = 8; index < ville.Count - 1; index++)
                    {
                        string xpos = ville[index];
                        string ypos = ville[index+1];
                        Coordonnees cc2 = new Coordonnees(Convert.ToInt32(xpos), Convert.ToInt32(ypos));
                        InterfaceJeu.Case caseTT = ImplementationJeu.Jeu.Instance.Carte.obtenirCase(cc2);
                        villeToAdd.casesOccupees.Add(caseTT);
                    }

                    j.civilisation.villes.Add(villeToAdd);
                }

                partieReprise.Joueurs.Add(j);
            }
        }
    }
}
